/*
* Copyright (C) 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.sites.liberation.util;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.auth.oauth2.TokenResponseException;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeRequestUrl;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeTokenRequest;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.gdata.client.sites.SitesService;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.sites.liberation.export.SiteExporter;
import com.google.sites.liberation.export.SiteExporterModule;
import com.google.sites.liberation.imprt.SiteImporter;
import com.google.sites.liberation.imprt.SiteImporterModule;
/**
* Provides a GUI for initiating a Sites import or export.
*
* @author bsimon@google.com (Benjamin Simon)
*/
public class GuiMain {
private static final Logger LOGGER = Logger.getLogger(GuiMain.class
.getCanonicalName());
private List<String> SCOPES = Arrays
.asList("https://sites.google.com/feeds");
private String CLIENT_ID = "457238310484-d7jjdra9vvij0ubk3k7vr59n8cb7eceh.apps.googleusercontent.com";
private String REDIRECT_URI = "urn:ietf:wg:oauth:2.0:oob";
private Credential credential = null;
private JFrame optionsFrame;
private JFrame progressFrame;
private JTextField hostField;
private JTextField domainField;
private JTextField webspaceField;
private JTextField tokenField;
private JTextField fileField;
private JFileChooser fileChooser;
private JCheckBox revisionsCheckBox;
private JTextArea textArea;
private JProgressBar progressBar;
private JButton doneButton;
private GuiMain() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException e) {
LOGGER.log(Level.WARNING, "Unable to set look and feel.", e);
} catch (InstantiationException e) {
LOGGER.log(Level.WARNING, "Unable to set look and feel.", e);
} catch (IllegalAccessException e) {
LOGGER.log(Level.WARNING, "Unable to set look and feel.", e);
} catch (UnsupportedLookAndFeelException e) {
LOGGER.log(Level.WARNING, "Unable to set look and feel.", e);
}
initOptionsFrame();
initProgressFrame();
}
private void initOptionsFrame() {
optionsFrame = new JFrame("Sites Import/Export");
JPanel mainPanel = new JPanel();
GridLayout layout = new GridLayout(0, 2);
mainPanel.setLayout(layout);
mainPanel.add(new JLabel(" Host: "));
hostField = new JTextField("sites.google.com");
mainPanel.add(hostField);
mainPanel.add(new JLabel(" Domain: "));
domainField = new JTextField();
mainPanel.add(domainField);
mainPanel.add(new JLabel(" Webspace: "));
webspaceField = new JTextField();
mainPanel.add(webspaceField);
mainPanel.add(new JLabel(" Import/Export Revisions: "));
revisionsCheckBox = new JCheckBox();
mainPanel.add(revisionsCheckBox);
fileField = new JTextField();
fileField.setEditable(false);
fileChooser = new JFileChooser();
JButton directoryButton = new JButton("Choose Target Directory");
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
directoryButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int result = fileChooser.showOpenDialog(optionsFrame);
if (result == JFileChooser.APPROVE_OPTION) {
fileField.setText(fileChooser.getSelectedFile().getPath());
}
}
});
mainPanel.add(directoryButton);
mainPanel.add(fileField);
JButton openBrowserButton = new JButton("Get a token from browser");
openBrowserButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
openBrowserAndGetToken();
}
});
mainPanel.add(openBrowserButton);
tokenField = new JTextField();
mainPanel.add(tokenField);
mainPanel.add(new JPanel());
mainPanel.add(new JPanel());
JButton importButton = new JButton("Import to Sites");
importButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (checkArguments()) {
startAction(false);
}
}
});
mainPanel.add(importButton);
JButton exportButton = new JButton("Export from Sites");
exportButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (checkArguments()) {
startAction(true);
}
}
});
mainPanel.add(exportButton);
mainPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
optionsFrame.getContentPane().add(mainPanel);
optionsFrame.pack();
optionsFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
optionsFrame.setVisible(true);
}
private void initProgressFrame() {
progressFrame = new JFrame("Progress");
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
progressBar = new JProgressBar();
progressBar.setMinimum(0);
progressBar.setMaximum(100);
progressBar.setPreferredSize(new Dimension(500, 25));
JPanel progressPanel = new JPanel();
progressPanel.add(progressBar);
progressPanel.setBorder(new EmptyBorder(10, 0, 0, 0));
mainPanel.add(progressPanel, BorderLayout.NORTH);
textArea = new JTextArea();
textArea.setRows(20);
textArea.setEditable(false);
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.setBorder(new EmptyBorder(10, 10, 10, 10));
mainPanel.add(scrollPane, BorderLayout.CENTER);
doneButton = new JButton("Done");
doneButton.setPreferredSize(new Dimension(495, 25));
doneButton.setEnabled(false);
doneButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
doneButton.setEnabled(false);
progressFrame.setVisible(false);
optionsFrame.setVisible(true);
}
});
JPanel donePanel = new JPanel();
donePanel.setLayout(new BorderLayout());
donePanel.add(doneButton, BorderLayout.CENTER);
donePanel.setBorder(new EmptyBorder(0, 10, 10, 10));
mainPanel.add(donePanel, BorderLayout.SOUTH);
progressFrame.getContentPane().add(mainPanel);
progressFrame.pack();
progressFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private void openBrowserAndGetToken() {
// Step 1: Authorize -->
String authorizationUrl = new GoogleAuthorizationCodeRequestUrl(
CLIENT_ID, REDIRECT_URI, SCOPES).build();
try {
// Point or redirect your user to the authorizationUrl.
java.awt.Desktop.getDesktop().browse(new URI(authorizationUrl));
} catch (Exception e) {
LOGGER.warning("Unable to open browser: " + e.toString());
LOGGER.info("Go to: " + authorizationUrl);
JOptionPane.showMessageDialog(optionsFrame, "Cannot open browser. Check the console for the necessary URL.",
"Error", JOptionPane.ERROR_MESSAGE);
}
// End of Step 1 <--
}
/**
* Retrieve OAuth 2.0 credentials.
*
* @return OAuth 2.0 Credential instance.
* @throws IOException
*/
private Credential getCredentials() throws IOException {
String code = tokenField.getText();
HttpTransport transport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
String CLIENT_SECRET = "EPME5fbwiNLCcMsnj3jVoXeY";
// Step 2: Exchange -->
GoogleTokenResponse response = new GoogleAuthorizationCodeTokenRequest(
transport, jsonFactory, CLIENT_ID, CLIENT_SECRET, code,
REDIRECT_URI).execute();
// End of Step 2 <--
// Build a new GoogleCredential instance and return it.
return new GoogleCredential.Builder()
.setClientSecrets(CLIENT_ID, CLIENT_SECRET)
.setJsonFactory(jsonFactory).setTransport(transport).build()
.setAccessToken(response.getAccessToken())
.setRefreshToken(response.getRefreshToken());
}
private void startAction(boolean export) {
optionsFrame.setVisible(false);
progressBar.setValue(0);
progressBar.setIndeterminate(true);
textArea.setText("");
progressFrame.setVisible(true);
new Thread(new ImportExportRunnable(export)).start();
}
private boolean checkArguments() {
if (hostField.getText().equals("")) {
error("Please provide a host name.");
return false;
}
if (webspaceField.getText().equals("")) {
error("Please provide a webspace (site name).");
return false;
}
if (tokenField.getText().equals("")) {
error("Please provide a token.");
return false;
}
if (fileChooser.getSelectedFile() == null) {
error("Please provide a target directory.");
return false;
}
try {
if (credential == null)
credential = getCredentials();
} catch (TokenResponseException e) {
error("The token is invalid!");
return false;
} catch (IOException e) {
error(e.toString());
return false;
}
return true;
}
private void error(String message) {
JOptionPane.showMessageDialog(optionsFrame, message, "Error",
JOptionPane.ERROR_MESSAGE);
}
/**
* Launches a new GuiMain, allowing a user to graphically initiate a Sites
* import or export.
*/
public static void main(String[] args) {
new GuiMain();
}
private class ImportExportRunnable implements Runnable {
private boolean export;
ImportExportRunnable(boolean export) {
this.export = export;
}
@Override
public void run() {
String host = hostField.getText();
String domain = (domainField.getText().equals("")) ? null
: domainField.getText();
String webspace = webspaceField.getText();
boolean revisions = revisionsCheckBox.isSelected();
File directory = fileChooser.getSelectedFile();
String applicationName = "sites-liberation-5";
SitesService sitesService = new SitesService(applicationName);
sitesService.setOAuth2Credentials(credential);
if (export) {
Injector injector = Guice.createInjector(new SiteExporterModule());
SiteExporter siteExporter = injector.getInstance(SiteExporter.class);
siteExporter.exportSite(host, domain, webspace, revisions,
sitesService, directory, new GuiProgressListener(progressBar, textArea));
} else {
Injector injector = Guice.createInjector(new SiteImporterModule());
SiteImporter siteImporter = injector.getInstance(SiteImporter.class);
siteImporter.importSite(host, domain, webspace, revisions,
sitesService, directory, new GuiProgressListener(progressBar, textArea));
}
doneButton.setEnabled(true);
}
}
}